package org.luxor.commons.storage.client.minio;

import io.minio.*;
import org.apache.commons.io.IOUtils;
import org.luxor.commons.core.utils.StrKit;
import org.luxor.commons.storage.client.AbstractStorageClient;
import org.luxor.commons.storage.client.AbstractStorageProperties;
import org.luxor.commons.storage.constant.StorageType;
import org.luxor.commons.storage.exception.StorageServiceException;
import org.luxor.commons.storage.exception.StorageTypeNotSupportedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;

/**
 * Minio 文件存储服务
 *
 * @author Mr.yan @date 2019/12/15
 */
public class MinioStorageClient extends AbstractStorageClient {
    private static final Logger logger = LoggerFactory.getLogger(MinioStorageClient.class);
    /**
     * Minio 全局配置项
     */
    private final MinioProperties properties;

    private MinioClient client;

    public MinioStorageClient(MinioProperties properties) {
        this.properties = properties;
        if (this.isEnabled()) {
            this.init();
        }
    }

    @Override
    public AbstractStorageProperties getConfig() {
        return this.properties;
    }

    @Override
    public boolean isEnabled() {
        return this.properties.isEnabled();
    }

    private void init() {
        logger.info("Initialization Minio open ( Running Minio Connector)");
        try {
            this.client = MinioClient.builder()
                    .endpoint(properties.getEndPoint())
                    .region(properties.getRegion())
                    .credentials(properties.getAccessKey(), properties.getSecretKey())
                    .build();
            logger.info("Initialize Minio Connector Success,bye");
        } catch (Throwable e) {
            logger.error("Initialize Minio Connector Failure!", e);
            throw e;
        }
    }

    @Override
    public String upload(byte[] fileByte, String fileName, String suffix) {
        if (!this.isEnabled()) {
            logger.error("[未开启] Minio分布式存储功能");
            throw new StorageTypeNotSupportedException("[未开启] Minio分布式存储功能");
        }
        BufferedInputStream inputStream = null;
        try {
            String fileFullPath = getFilePath(StorageType.MINIO, properties.getPrefix(), fileName, suffix);
            logger.info("上传文件,路径:{}", fileFullPath);
            inputStream = new BufferedInputStream(new ByteArrayInputStream(fileByte));
            String name = fileFullPath.startsWith(StrKit.SLASH) ? fileFullPath.substring(1) : fileFullPath;
            client.putObject(PutObjectArgs.builder()
                    .region(properties.getRegion())
                    .bucket(properties.getBucketName())
                    .object(name)
                    .stream(inputStream, inputStream.available(), -1)
                    .build());
            return fileFullPath;
        } catch (Exception e) {
            logger.error("上传文件失败，请核对Minio配置信息", e);
            throw new StorageServiceException("上传文件失败，请核对Minio配置信息", e);
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
    }

    @Override
    public byte[] download(String fileFullPath) {
        if (!this.isEnabled()) {
            logger.error("[未开启] Minio分布式存储功能. fileFullPath:{}", fileFullPath);
            throw new StorageTypeNotSupportedException("[未开启] Minio分布式存储功能");
        }
        logger.info("下载文件,路径:{}", fileFullPath);

        GetObjectResponse response = null;
        try {
            String name = fileFullPath.startsWith(StrKit.SLASH) ? fileFullPath.substring(1) : fileFullPath;
            response = client.getObject(GetObjectArgs.builder()
                    .region(properties.getRegion())
                    .bucket(properties.getBucketName())
                    .object(name).build());
            return IOUtils.toByteArray(response);
        } catch (Exception e) {
            logger.error("下载文件失败，请核对Minio配置信息", e);
            throw new StorageServiceException("下载文件失败，请核对Minio配置信息", e);
        } finally {
            IOUtils.closeQuietly(response);
        }
    }

    @Override
    public void delete(String fileFullPath) {
        if (!this.isEnabled()) {
            logger.error("[未开启] Minio分布式存储功能. fileFullPath:{}", fileFullPath);
            throw new StorageTypeNotSupportedException("[未开启] Minio分布式存储功能");
        }
        logger.info("删除文件,路径:{}", fileFullPath);

        try {
            String name = fileFullPath.startsWith(StrKit.SLASH) ? fileFullPath.substring(1) : fileFullPath;
            client.removeObject(RemoveObjectArgs.builder()
                    .region(properties.getRegion())
                    .bucket(properties.getBucketName())
                    .object(name).build());
        } catch (Exception e) {
            logger.error("删除文件失败，请核对Minio配置信息", e);
            throw new StorageServiceException("删除文件失败，请核对Minio配置信息", e);
        }
    }

}
